# -*- coding: utf-8 -*-
import os
import re
import sys
import time
from collections import Iterable
from datetime import datetime

from util.selenium.common.exceptions import NoSuchElementException, ElementNotVisibleException, TimeoutException, \
    NoAlertPresentException
from util.selenium.webdriver.common.alert import Alert
from util.selenium.webdriver.common.by import By
from util.selenium.webdriver.support import expected_conditions as EC
from util.selenium.webdriver.support.select import Select
from util.selenium.webdriver.support.wait import WebDriverWait

from util.DataQuery import hzflowOperation
from util.DataQuery.DbTools import DbTools
from util.g import g
from settings import ResTypeMapping, TypeSqlMapping, res_base_sql, web_type, online_config, materials_path, site_type, \
    MultiRecordList, CLASSMODELMAPPING, rule_json, base_path, replace_map
from util.inform.sendEmail import sendEmail


class alert_is_present(object):
    """ Expect an alert to be present."""

    # def __init__(self, driver):
    #     self.driver = driver

    def __call__(self, driver):
        try:
            alert = driver.switch_to.alert
            return alert
        except NoAlertPresentException:
            return False

class keyword_is_present(object):

    def __init__(self, keyword):
        self.keyword = keyword


    def __call__(self, driver):
        try:
            text = driver.page_source
            if self.keyword in text:
                return True
            else:
                return False
        except Exception:
            return False



class BM():

    @staticmethod
    def get_cookie(driver=None):
        temp = {}
        cookies = driver.get_cookies()
        # print("driver-get-cookies: {}".format(cookies))
        for item in cookies:
            name = item.get("name")
            if name in g.cookie:
                if item.get("value"):
                    g.cookie[name] = item.get("value")
                    temp[name] = item.get("value")
        return temp

    @classmethod
    def close_current_page(cls, driver=None):
        driver.execute_script('window.opener=null;window.close();')

    @staticmethod
    def get_material_path():
        return materials_path + "\\{}_{}\\{}\\{}_{}".format(site_type, g.year, web_type, site_type, g.co_id)

    # 检测附件是否存在 大小是否合适
    @staticmethod
    def check_file(file_path=None, size=None):
        if not file_path or not size:
            return False
        if os.path.isfile(file_path):
            if os.path.getsize(file_path) < (size * 1024 * 1024):
                return True
        return False

    @staticmethod
    def get_first(li:list, ty:type=str):
        if type(li) == str:
            return li
        if len(li) < 1:
            return ""
        if li[0] is None:
            return ""
        return li[0]

    @classmethod
    def handle_str(cls, s):
        for k, v in replace_map.items():
            if k in s:
                s = s.replace(k, v)
        return s

    # 获取 本机ip及当前进程号
    @staticmethod
    def get_host():
        from configparser import ConfigParser

        cfg = ConfigParser()
        cfg.read("{}\\config.ini".format(base_path))
        host_str = cfg.get("runtime", "host")
        # return str(socket.gethostbyname(socket.gethostname()))
        return host_str

    @staticmethod
    def get_hostprocess():
        return "{}".format(BM.get_host(), os.getpid())

    @staticmethod
    def get_current_year():
        return datetime.now().year

    @staticmethod
    def get_file_operate(status, operate):
        return {"biz_code": status.get("stat_id"), "co_id": g.co_id, "year": g.year,
                "file_path": BM.get_material_path(), "description": "0", "operate": operate}

    @staticmethod
    def driver_wait(driver=None, ele_loc=(), time=10, is_not=False):
        if not is_not:
            WebDriverWait(driver, timeout=time, poll_frequency=0.5).until(
                EC.presence_of_all_elements_located(ele_loc))
        else:
            WebDriverWait(driver, timeout=time, poll_frequency=0.5).until_not(
                EC.presence_of_all_elements_located(ele_loc))

    @staticmethod
    def wait_keyword(keyword, driver=None, time=8, is_not=False):
        try:
            if not is_not:
                WebDriverWait(driver, timeout=time, poll_frequency=0.8).until(keyword_is_present(keyword))
            else:
                WebDriverWait(driver, timeout=time, poll_frequency=0.8).until_not(keyword_is_present(keyword))
        except TimeoutException as err:
            driver.quit()
            return True
        return False

    @classmethod
    def remove_dir(cls, dir=""):
        """ 递归方法
        :param dir: 要删除的目录或文件
        :return:
        """
        if os.path.exists(dir):
            if not os.path.isdir(dir):
                os.remove(dir)
                return
            x = os.listdir(dir)
            for i in x:
                new_path = os.path.join(dir, i)
                if not os.path.isdir(new_path):
                    os.remove(new_path)
                    return BM.remove_dir(os.path.dirname(new_path))
                else:
                    BM.remove_dir(new_path)
                # os.rmdir(new_path)
        os.rmdir(dir)

    @staticmethod
    def wait_ele_exist(driver=None, ele_loc=(), time=10, is_not=False):
        try:
            if not is_not:
                WebDriverWait(driver, timeout=time, poll_frequency=0.5).until(
                    EC.presence_of_all_elements_located(ele_loc))
            else:
                WebDriverWait(driver, timeout=time, poll_frequency=0.5).until_not(
                    EC.presence_of_all_elements_located(ele_loc))
        except TimeoutException as err:
            return False
        else:
            return True

    # #sub-frame-error-details
    # 找不到 slb.chinatorch.gov.cn 的服务器 IP 地址。 所在的元素
    @staticmethod
    def wait(driver=None, ele_loc=(), time=10, is_not=False):
        # TODO 循环等待一定次数，若持续失败则关闭浏览器，等待一段时间后重新启动。
        quit = False
        for i in range(g.times):
            try:
                if not is_not:
                    WebDriverWait(driver, timeout=time, poll_frequency=0.5).until(
                        EC.presence_of_all_elements_located(ele_loc))
                else:
                    WebDriverWait(driver, timeout=time, poll_frequency=0.5).until_not(
                        EC.presence_of_all_elements_located(ele_loc))
            except TimeoutException as err:
                if BM.isElementExist(element=(By.CSS_SELECTOR, "#sub-frame-error-details"), driver=driver):
                    hzflowOperation.hzflowOperation.update_host_process(
                        obj=hzflowOperation.hzflowOperation.get_log(g.co_id, g.year), mark_info="")
                    driver.quit()
                    os._exit(0)
                g.logger.error("element is not found: {}".format(ele_loc))
                url = driver.current_url
                if not url.startswith("http"):
                    quit = True
                    break
                else:
                    continue
            else:
                break
        else:
            # 将 状态设置为空值
            hzflowOperation.hzflowOperation.update_host_process(
                obj=hzflowOperation.hzflowOperation.get_log(g.co_id, g.year), mark_info="")
            driver.quit()
            os._exit(0)
        if quit is True:
            hzflowOperation.hzflowOperation.update_host_process(
                obj=hzflowOperation.hzflowOperation.get_log(g.co_id, g.year), mark_info="")
            driver.quit()
            os._exit(0)

    @staticmethod
    def get_ele(driver=None, ele_loc=(), time=10):
        BM.wait(driver=driver, ele_loc=ele_loc, time=time)
        return driver.find_element(*ele_loc)

    @staticmethod
    def get_ele_text(driver=None, ele_loc=(), time=10):
        BM.wait(driver=driver, ele_loc=ele_loc, time=time)
        try:
            js = """return document.querySelector("{}").selectedOptions[0].text""".format(ele_loc[1])
            return driver.execute_script(js)
        except Exception as err:
            return ""

    @staticmethod
    def click(driver=None, ele_loc:tuple=(), wait:str=""):
        if not wait or wait == "wait":
            BM.wait(driver=driver, ele_loc=ele_loc)
        elif wait == "driver_wait":
            BM.driver_wait(driver=driver, ele_loc=ele_loc)
        if ele_loc[0] == By.CSS_SELECTOR:
            click_js = "document.querySelector('{}').click()".format(ele_loc[1])
            driver.execute_script(click_js)
        elif ele_loc[0] == By.XPATH:
            click_js = '''document.evaluate("{}", document).iterateNext().click()'''.format(ele_loc[1])
            driver.execute_script(click_js)
        else:
            driver.find_element(*ele_loc).click()

    @staticmethod
    def input(driver=None, ele_loc=(), keys="", is_clear=True):
        if type(keys) == float: keys = str(keys)
        if type(keys) == str:
            keys = keys.strip()
            keys = keys.replace("<sub>", "").replace("</sub>", "")
        BM.wait(driver=driver, ele_loc=ele_loc)
        if not keys and keys != 0:
            keys = ""
        if type(keys) == str and keys == u"无":
            driver.find_element(*ele_loc).clear()
            return
        if is_clear:
            driver.find_element(*ele_loc).clear()
        if type(keys) == str and "CO2" in keys:
            # if "CO2" in keys:
            js = "document.querySelector('{}').value='{}'".format(ele_loc[1], keys)
            driver.execute_script(js)
        else:
            driver.find_element(*ele_loc).send_keys(keys)

    @staticmethod
    def alert_accept(driver=None):
        # alert = EC.alert_is_present()(driver)
        alert = WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5).until(alert_is_present())

        if alert:
            a = alert.text
            alert.accept()
            return a
        return "nothing to delete"

    @staticmethod
    def delete_all(driver, page_num_loc, select_all_loc, delete_btn_loc):
        page_nums = driver.find_elements(*page_num_loc)
        page = len(page_nums)
        for i in range(page):
            BM.click(driver=driver, ele_loc=select_all_loc)
            BM.click(driver=driver, ele_loc=delete_btn_loc)
            weather = BM.alert_accept(driver=driver)
            tip = BM.alert_accept(driver=driver)
            g.logger.info(weather)
            g.logger.info(tip)

    @staticmethod
    def check_alert_and_get_text(driver=None):
        alert = None
        try:
            # alert = EC.alert_is_present()(driver)
            alert = WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5).until(alert_is_present())
        except Exception as err:
            return False
        else:
            # g.logger.info("alert: {} alert_text: {}".format(alert, alert.text))
            if type(alert) == Alert:
                a = alert
                alert.accept()
                return a
            return alert

    @staticmethod
    def input_textarea_info(driver=None, ele_loc=(), keys=""):
        keys = keys.replace("\t", "").replace(" ", "").replace("\xa0", "")
        li = keys.split("\n")
        BM.wait(driver=driver, ele_loc=ele_loc)
        driver.find_element(*ele_loc).clear()
        li_num = len(li)
        for ind, i in enumerate(li):
            driver.find_element(*ele_loc).send_keys(i)
            if ind < li_num - 1:
                driver.find_element(*ele_loc).send_keys("\n")

    @staticmethod
    def switch_to_frame(driver=None, ele_loc=()):
        BM.wait(driver=driver, ele_loc=ele_loc)
        driver.switch_to.frame(driver.find_element(*ele_loc))

    @staticmethod
    def isElementExist(element=None, driver=None):
        """
        :param element: 关于元素定位的元组 (By.xxx, "")
        :return: 若该元素存在则返回该元素, 否则返回 False
        """
        try:
            ele = driver.find_element(*element)
        except NoSuchElementException as err:
            return False
        else:
            return True

    @staticmethod
    def isElementExistById(ID=None, driver=None):
        """
        :param element: 关于元素定位的元组 (By.xxx, "")
        :return: 若该元素存在则返回该元素, 否则返回 False
        """
        try:
            ele = driver.find_element_by_id(ID)
        except NoSuchElementException as err:
            return False
        else:
            return True

    @staticmethod
    def is_element_block(driver=None, ele_loc=()):
        try:
            driver.find_element(*ele_loc).text
        except (ElementNotVisibleException, NoSuchElementException) as err:
            return False
        else:
            return True

    @staticmethod
    def cut_over_frame(driver: object = None, selector_loc: object = ""):
        if not driver:
            raise NameError("driver is not defind. custom--")
        if type(selector_loc) == "str":
            driver.switch_to.frame(driver.find_element_by_css_selector(selector_loc))
        driver.switch_to.frame(driver.find_element(*selector_loc))

    # @classmethod
    # def get_select_value(cls, selector_loc, driver=None):
    #     BM.wait(driver=driver, ele_loc=selector_loc)

    @staticmethod
    def select_value_choice(selector_loc, text_value, driver=None):
        if not driver:
            raise NameError("driver is not defind. custom--")
        # text_value = str(text_value).replace(" ", "")
        if not text_value or text_value == "":
            return
        BM.wait(driver=driver, ele_loc=selector_loc)
        cer_body_select = driver.find_element(*selector_loc)
        try:
            if " " in text_value:
                option = BM.get_ele(driver=driver,
                                    ele_loc=(By.XPATH, "//option[contains(text(),'{}')]".format(text_value)))
                value = option.get_attribute("value")
                Select(cer_body_select).select_by_value(value=value)
            else:
                Select(cer_body_select).select_by_visible_text(text_value)
        except NoSuchElementException as err:
            class_name = getattr(g, "current_class")
            record_var = "{}Data".format(class_name)
            rd_id = CLASSMODELMAPPING.get(class_name).get("rd_id")
            rd_name = CLASSMODELMAPPING.get(class_name).get("rd_name")
            biz_code_str = CLASSMODELMAPPING.get(class_name).get("biz_code")
            biz_name_str = (CLASSMODELMAPPING).get(class_name).get("biz_name")
            if not hasattr(g, record_var):
                biz_code = None
                biz_name = None
            else:
                biz_code = "" if not biz_code_str else getattr(g, record_var).get(biz_code_str)
                biz_name = "" if not biz_name_str else getattr(g, record_var).get(biz_name_str)
            msg = "{} selector: {} text_value: {}, err: {}".format(sys._getframe().f_code.co_name, selector_loc,
                                                                   text_value, err)
            g.logger.error(msg)
            hzflowOperation.hzflowOperation.add_reason(co_id=g.co_id, year=g.year, fb_time=g.status.get("fb_time"),
                                                       rt_id=rd_id, rt_name=rd_name, biz_code=biz_code,
                                                       biz_name=biz_name, rsn_desc=msg)
            a = sendEmail(subject="autoflow_{}_{}".format(web_type, g.co_id),
                          content="{} {}".format(g.status.get("entname"), msg))
            a.content = "{} {}".format(g.status.get("entname"), msg)
            a.send_mail()

    @staticmethod
    def select_domain_just(driver=None, selector_loc=(), text_value=""):
        BM.wait(driver=driver, ele_loc=selector_loc)
        cer_body_select = BM.get_ele(driver=driver, ele_loc=selector_loc)
        Select(cer_body_select).select_by_visible_text(text_value)

    @staticmethod
    def select_domain(selector_loc, text_value, driver=None, tech_fieldname="",
                      domain1=(By.CSS_SELECTOR, 'select#onemain'), domain2=(By.CSS_SELECTOR, 'select#scdmain')):
        try:
            if not text_value:
                return
            BM.wait(driver=driver, ele_loc=selector_loc)
            while True:
                if text_value in driver.page_source:
                    break
                else:
                    a = selector_loc[1]
                    if "thdmain" not in a:
                        onchange_js = "document.querySelector('{}').onchange()".format(selector_loc[1])
                        try:
                            driver.execute_script(onchange_js)
                        except Exception as err:
                            g.logger.error("touch element: {} error: {} js: {}".format(selector_loc, err, onchange_js))
                    time.sleep(0.5)

                    loc = "select#onemain"
                    if "thd" in selector_loc[1]: loc = "select#scdmain"
                    # TODO 重新选择之前的 领域信息
                    for index, i in enumerate(tech_fieldname.split(",")):
                        if i != text_value:
                            if index == 0:
                                # BM.click(driver=driver, ele_loc=domain1)
                                BM.select_domain_just(driver=driver, selector_loc=domain1, text_value=i)
                            elif index == 1:
                                # BM.click(driver=driver, ele_loc=domain2)
                                BM.select_domain_just(driver=driver, selector_loc=domain2, text_value=i)
                        else:
                            break

            cer_body_select = BM.get_ele(driver=driver, ele_loc=selector_loc)
            Select(cer_body_select).select_by_visible_text(text_value)
            js = "return document.querySelector('{}').previousElementSibling.innerText".format(selector_loc[1])
            res = driver.execute_script(js)
            g.logger.info("text_value: {} res: {}".format(text_value, res))
            if res.strip() != text_value.strip():
                current_class = getattr(g, "current_class")
                msg = "{} --- {}\n选框未选中 text_value: {} res: {}".format(current_class,
                                                                       CLASSMODELMAPPING.get(current_class).get(
                                                                           "rd_name"),
                                                                       text_value, res)
                g.logger.error(msg)
                sendEmail(subject="autoflow_{}".format(g.co_id), content=msg).send_mail()
                BM.select_domain(selector_loc=selector_loc, text_value=text_value, driver=driver,
                                 tech_fieldname=tech_fieldname)
        except Exception as err:
            msg = "error: {} file: {} lines: {}".format(err,
                                                        err.__traceback__.tb_frame.f_globals[
                                                            "__file__"],
                                                        err.__traceback__.tb_lineno)
            g.logger.error(msg)
            raise Exception(msg)
        # js = """$('{} option[text="{}"]').attr('selected', true)"""

    @classmethod
    def touch_method(cls, driver=None, select="", method="", wait=None):
        js_str = f"document.querySelector('%s').%s();" % (select, method)
        try:
            driver.execute_script(js_str)
        except Exception as err:
            print(err)
        if wait: time.sleep(wait)

    @classmethod
    def display_element(cls, driver=None, ele_loc=(), display=''):
        js_str = "document.querySelector('{ele_selector}').style.display='{display}'".format(ele_selector=ele_loc[1],
                                                                                             display=display)
        driver.execute_script(js_str)

    ######### 保存按钮点击
    @staticmethod
    def global_click_btn(btn_loc, driver=None, class_name="", file_path=None):
        if not class_name:
            class_name = getattr(g, "current_class")
        record_var = "{}Data".format(class_name)
        rd_id = CLASSMODELMAPPING.get(class_name).get("rd_id")
        rd_name = CLASSMODELMAPPING.get(class_name).get("rd_name")
        biz_code_str = CLASSMODELMAPPING.get(class_name).get("biz_code")
        biz_name_str = (CLASSMODELMAPPING).get(class_name).get("biz_name")
        if not hasattr(g, record_var):
            biz_code = None
            biz_name = None
        else:
            biz_code = "" if not biz_code_str else getattr(g, record_var).get(biz_code_str)
            biz_name = "" if not biz_name_str else getattr(g, record_var).get(biz_name_str)
        #
        # if not class_name:
        #     class_name = getattr(g, 'current_class')
        record_var = "{}Data".format(class_name)
        class_record = None if not hasattr(g, record_var) else getattr(g, record_var)
        if not driver:
            raise NameError("driver is not defind. custom--")
        BM.click(driver=driver, ele_loc=btn_loc)
        # BM.touch_method(driver=driver, select=btn_loc[1], method="click", wait=0.5)
        # # # # # # TODO 这里点击保存之后 需要判断 弹框中的提示信息 确定是否保存成功

        alert = None
        try:
            alert = WebDriverWait(driver=driver, timeout=5, poll_frequency=0.5).until(alert_is_present())
        except TimeoutException as err:
            g.logger.error(err)
        if not alert:
            return True
        else:
            text = alert.text
            alert.accept()
        if u"成功" in text:
            g.logger.info("{}: {}; alert: {}".format(record_var, class_record, text))
            return True
        else:
            # if class_name == "WriteIPForm" and u"正在" in text:
            #     # if u"未检索到该知识产权" in
            #     g.logger.error("{}: {}; 保存失败: alert_text: {}".format(record_var, class_record, text))
            #     hzflowOperation.hzflowOperation.add_reason(co_id=g.co_id, year=g.year, fb_time=g.status.get("fb_time"),
            #                                                rt_id=rd_id, rt_name=rd_name, biz_code=biz_code,
            #                                                biz_name=biz_name, rsn_desc=text)
            #     BM.click(driver=driver, ele_loc=btn_loc)
            #     alert = WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5).until(alert_is_present())
            #     if not alert:
            #         g.logger.error("not alert appear")
            #         return False
            #     else:
            #         tip = alert.text
            #
            #         if u"成功" in tip:
            #             g.logger.info("alert_text: {}".format(tip))
            #             hzflowOperation.hzflowOperation.add_reason(co_id=g.co_id, year=g.year,
            #                                                        fb_time=g.status.get("fb_time"),
            #                                                        rt_id=rd_id, rt_name=rd_name, biz_code=biz_code,
            #                                                        biz_name=biz_name, rsn_desc=tip)
            #             alert.accept()
            #             return True
            #         else:
            #             tip_str = "{}: {}; 保存失败: alert_text: {}".format(record_var, class_record, tip)
            #             g.logger.error(tip_str)
            #             hzflowOperation.hzflowOperation.add_reason(co_id=g.co_id, year=g.year,
            #                                                        fb_time=g.status.get("fb_time"), rt_id=rd_id,
            #                                                        rt_name=rd_name, biz_code=biz_code,
            #                                                        biz_name=biz_name, rsn_desc=tip_str)
            #             alert.accept()
            #             return False
            if class_name == "WriteIPForm" and \
                    (u"正在校验" in text or u"未检索到" in text or u"上传附件" in text or u"上传知识产权证明材料" in text):
                tip_str = "{} IP未检索到 data: {} \n tip:{}".format(record_var, class_record, text)
                BM.upload_replace(driver=driver, class_name="WriteIPForm", file_path=file_path)
                hzflowOperation.hzflowOperation.add_reason(co_id=g.co_id, year=g.year, fb_time=g.status.get("fb_time"),
                                                           rt_id=rd_id, rt_name=rd_name, biz_code=biz_code,
                                                           biz_name=biz_name, rsn_desc=tip_str, add_desc=2)
                # TODO 调用该方法 点击保存
                BM.global_click_btn(btn_loc=btn_loc, driver=driver, class_name=class_name)
                # a.send_mail()
                # g.logger.error("{} 保存失败 data: {} \n tip:{}".format(record_var, class_record, text))
                # return False
            elif u"知识产权无效" in text:
                tip_str = "{} 知识产权无效 data: {} \n tip:{}".format(record_var, class_record, text)
                BM.upload_replace(driver=driver, class_name="WriteIPForm", file_path=file_path)
                a = sendEmail(subject="autoflow", content=tip_str)
                hzflowOperation.hzflowOperation.add_reason(co_id=g.co_id, year=g.year, fb_time=g.status.get("fb_time"),
                                                           rt_id=rd_id, rt_name=rd_name, biz_code=biz_code,
                                                           biz_name=biz_name, rsn_desc=tip_str, add_desc=2)
                BM.global_click_btn(btn_loc=btn_loc, driver=driver, class_name=class_name)
                a.send_mail()
                g.logger.error(tip_str)
                # return False
            else:
                message = "{}: {}; alert: {}".format(record_var, class_record, text)
                if u"成功" in text:
                    return True
                g.logger.info(message)
                sendEmail(subject="autoflow", content=message).send_mail()

        return False

        # print(f"{class_info}" + f"点击——保存————————" * 10)

    @staticmethod
    def wait_file(file_path, size=None):
        while True:
            if os.path.isfile(file_path):
                if size:
                    if os.path.getsize(file_path) < (size * 1024 * 1024):
                        break
                else:
                    break
            else:
                time.sleep(1)

    @staticmethod
    def upload_replace(btn_loc=None, driver=None, class_name="", _id=None, file_path=None):
        if btn_loc is None:
            btn_loc = (By.CSS_SELECTOR, 'div#fileId a')
        path = os.path.join(materials_path, "replace.pdf")
        download_loc = (By.CSS_SELECTOR, ".progress-button.uploadBtn")
        if file_path:
            path = file_path
        if BM.is_element_block(ele_loc=download_loc, driver=driver):
            g.logger.info("附件已上传 file={file}".format(file=path))
            return
        upload_loc = (By.CSS_SELECTOR, "#{file_id}".format(file_id=BM.get_file_id(driver=driver, ele_loc=btn_loc)))
        if class_name in MultiRecordList:
            div_loc = (By.CSS_SELECTOR, "#uniform-yyzzFile")
            if BM.isElementExist(element=div_loc, driver=driver):
                BM.display_element(driver=driver, ele_loc=div_loc, display="block")
        BM.display_element(driver=driver, ele_loc=upload_loc, display="block")
        BM.input(driver=driver, ele_loc=upload_loc, keys=path)
        # alert = EC.alert_is_present()(driver)
        # BM.click(driver=driver, ele_loc=btn_loc)
        alert = None
        try:
            alert = WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5).until_not(alert_is_present())
        except TimeoutException as err:
            g.logger.info("附件格式正确: {}".format(path))
        if not alert:
            # g.logger.info("没有alert框弹出")
            return False
        else:
            text = alert.text
            g.logger.info("上传提示：{tishi} 上传 file={file}".format(tishi=text, file=path))
            alert.accept()
        if class_name in MultiRecordList:
            div_loc = (By.CSS_SELECTOR, "#uniform-yyzzFile")
            if BM.isElementExist(element=div_loc, driver=driver):
                BM.display_element(driver=driver, ele_loc=div_loc, display="none")
                time.sleep(0.2)

    # # # # 上传按钮点击
    @staticmethod
    def click_upload_attach(btn_loc, driver=None, class_name="", _id=None):
        g.logger.info("need_file: {}".format(g.need_file))
        if g.need_file is False:
            return None
        res_type = ResTypeMapping.get(class_name)

        file_path = BM.get_material_path() + "\\{}\\{}_{}{}".format(res_type.upper(), res_type, str(_id).zfill(2),
                                                                    ".pdf")
        g.logger.info("{}: {}".format(res_type, file_path))
        while True:
            if os.path.isfile(file_path):
                break
            else:
                time.sleep(1)

        download_loc = (By.CSS_SELECTOR, ".progress-button.uploadBtn")
        if BM.is_element_block(ele_loc=download_loc, driver=driver):
            g.logger.info("附件已上传 file={file}".format(file=file_path))
            return
        upload_loc = (By.CSS_SELECTOR, "#{file_id}".format(file_id=BM.get_file_id(driver=driver, ele_loc=btn_loc)))
        if class_name in MultiRecordList:
            div_loc = (By.CSS_SELECTOR, "#uniform-yyzzFile")
            if BM.isElementExist(element=div_loc, driver=driver):
                BM.display_element(driver=driver, ele_loc=div_loc, display="block")
        BM.display_element(driver=driver, ele_loc=upload_loc, display="block")
        BM.input(driver=driver, ele_loc=upload_loc, keys=file_path)
        alert = None
        try:
            alert = WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5).until_not(alert_is_present())
        except TimeoutException as err:
            g.logger.info("附件格式正确: {}".format(file_path))
        if not alert:
            # g.logger.info("没有alert框弹出")
            return False
        else:
            text = alert.text
            g.logger.info("上传提示：{tishi} 上传 file={file}".format(tishi=text, file=file_path))
            alert.accept()
        if class_name in MultiRecordList:
            div_loc = (By.CSS_SELECTOR, "#uniform-yyzzFile")
            if BM.isElementExist(element=div_loc, driver=driver):
                BM.display_element(driver=driver, ele_loc=div_loc, display="none")
                time.sleep(0.2)
        return file_path

    @staticmethod
    # TODO 这里的附件类型 中部分是通过提示来获取 若提示更新，则需要更新setting中的 ResTypeMapping
    def click_upload(btn_loc=(), tip_loc=(), download_loc=(), driver=None, class_name=""):
        skip = False
        if g.need_file is False:
            return
        res_type_dict = ResTypeMapping.get(class_name)
        res_type = None
        year = None
        tip = None
        if isinstance(res_type_dict, str):
            res_type = res_type_dict
        if tip_loc:
            BM.wait(driver=driver, ele_loc=tip_loc)
            tip = driver.find_element(*tip_loc).text
            for k, v in res_type_dict.items():
                if k in tip:
                    res_type = v
                    break
            if res_type == None:
                g.logger.error("附件未上传 或 网站提示改变： tip={tip}".format(tip=tip))
                return
            material_year = BM.get_year(tip_str=tip)
            if material_year:
                year = BM.get_year(tip_str=tip)
        if not res_type:
            g.logger.error("附件未上传 或 网站提示改变： tip={tip}".format(tip=tip))
            return
        if not year:
            file_path = BM.get_material_path() + "\\{}{}".format(res_type, ".pdf")
        else:
            file_path = BM.get_material_path() + "\\{}\\{}_{}{}".format(res_type.upper(), res_type, year, ".pdf")
        if res_type == "buslic":
            file_path = BM.get_material_path() + "\\{}{}".format(res_type, ".png")
        g.logger.info("{}: {}".format(res_type, file_path))
        search = False
        need = None
        while True:
            if os.path.isfile(file_path):
                break
            else:
                if search is False:
                    need = BM.get_file_page(co_id=g.co_id, year=g.year, res_type=res_type,
                                            res_code=None if year is None else year)
                    search = True
                    if need is False:
                        break
                if res_type == "buslic":
                    skip = True
                    break
                else:
                    time.sleep(1)
        if need is False:
            return
        if skip is True:
            pass
        else:
            download_loc = (By.CSS_SELECTOR, ".progress-button.uploadBtn")
            if res_type == "hr":
                if BM.is_element_block(ele_loc=download_loc, driver=driver):
                    g.logger.info("附件已上传 file={file}".format(file=file_path))
                    return
            else:
                # if res_type != "cooperation":
                if class_name != "IARdmDesc":
                    btn_text = driver.find_element(*btn_loc).text
                    # print(btn_text, btn_loc, file_path, res_type, tip)
                    delete_loc = (btn_loc[0], btn_loc[1].replace(" a", " button"))
                    # print(u"点击下载" in btn_text, BM.is_element_block(ele_loc=delete_loc, driver=driver), delete_loc)
                    if u"点击下载" in btn_text and BM.is_element_block(ele_loc=delete_loc, driver=driver):
                        g.logger.info("附件已上传 file={file}".format(file=file_path))
                        return
            file_id = BM.get_file_id(driver=driver, ele_loc=btn_loc)
            if file_id == None:
                g.logger.info("附件已上传 file={file}".format(file=file_path))
                return
            upload_loc = (By.CSS_SELECTOR, "#{file_id}".format(file_id=file_id))
            div_loc = (By.CSS_SELECTOR, "#uniform-yyzzFile")
            if BM.isElementExist(element=div_loc, driver=driver):
                BM.display_element(driver=driver, ele_loc=div_loc, display="block")
            BM.display_element(driver=driver, ele_loc=upload_loc, display="block")
            BM.input(driver=driver, ele_loc=upload_loc, keys=file_path)
            # BM.touch_method(driver=driver, select="#{}".format(file_id), method="onchange")

            if res_type != "hr":
                delete_loc = (btn_loc[0], btn_loc[1].replace(" a", " button"))
                while True:
                    btn_ele = BM.get_ele(driver=driver, ele_loc=btn_loc)
                    # if btn_ele.get_attribute("data_loading") is None:
                    #     break
                    href = btn_ele.get_attribute("href")
                    # delete_ele = BM.get_ele(driver=driver, ele_loc=delete_loc)
                    delete_display_js = "return document.querySelector('{}').style.display".format(delete_loc[1])
                    display = driver.execute_script(delete_display_js)
                    # print("-------------", href)
                    if "javascripe:void(0);" not in href and "none" not in display:
                        break
            # BM.click(driver=driver, ele_loc=btn_loc)
            # alert = EC.alert_is_present()(driver)

            # alert = None
            # try:
            #     alert = WebDriverWait(driver=driver, timeout=10, poll_frequency=0.5).until_not(alert_is_present())
            # except TimeoutException as err:
            #     g.logger.info("附件格式正确:{}".format(file_path))
            # if not alert:
            #     return False
            # else:
            #     text = alert.text
            #     g.logger.info("附件上传提示 text={} file={}".format(text, file_path))
            #     alert.accept()
        # if BM.isElementExist(element=div_loc, driver=driver):
        #     BM.display_element(driver=driver, ele_loc=div_loc, display="none")
        #     time.sleep(1)
        # TODO 等待 按钮 变成 点击下载之后再

    @staticmethod
    def get_file_id(driver=None, ele_loc=()):
        a = driver.find_element(*ele_loc).get_attribute("onclick")
        if a == None:
            return a
        res = re.search('\'(.*?)\'', a)
        i = res.group().replace("\'", "")
        return i

    @staticmethod
    def get_rule_id(res_type="", year=None):
        for r in rule_json.get("content"):
            child = r.get("children")
            if year and child:
                calculate = year - datetime.now().year
                if child:
                    for c in child:
                        if c.get("type") == res_type and c.get("calculate") == calculate:
                            return c.get("id")
            elif r.get("type") == res_type:
                return r.get("id")

    @staticmethod
    def get_file_page(co_id=None, year=None, res_type=None, res_code=None):
        year_pa = None if res_code is None else res_code
        rule_id = BM.get_rule_id(res_type=res_type, year=year_pa)
        sql = """select file_start, file_end from ent_res_pdf where co_id={} and `year`={} and web_type='{}' and rule_id={} and {}""".format(
            co_id, year, web_type, rule_id, "" if res_code is None else " res_code={}".format(res_code))
        client_obj = DbTools.get_conn(db_config=online_config, database="hitech")
        cursor = client_obj.cursor(cursor=DbTools.dict_cursor)
        data = None
        try:
            cursor.execute(sql)
            data = cursor.fetchone()
        except Exception as err:
            g.logger.error("{} error sql={} err={}".format(sys._getframe().f_code.co_name, sql, err))
        finally:
            cursor.close()
            client_obj.close()
        if data is None:
            return False
        elif not all([data.get("file_start"), data.get("file_end")]):
            return False
        else:
            return True

    @classmethod
    def get_pdf_path(cls, co_id, biz_code, description):
        file_remote_path = DbTools.get_doc_path_by_info(co_id=co_id, biz_code=biz_code, description=description)
        # g.logger.info("file_remote_path: {}".format(file_remote_path))
        if file_remote_path is None:
            return ""
        if not file_remote_path.get("doc_path"):
            return ""
        file_remote_path = file_remote_path.get("doc_path")
        bucket_name, file_name = file_remote_path.split("/")
        local_path = materials_path + "\\original_files"
        if not os.path.exists(local_path):
            os.mkdir(local_path)
        path = os.path.join(local_path, file_name)
        return path

    # @staticmethod
    # def get_file_path(sql):
    #     # TODO 获取文件路径的地方， 后期可能会修改
    #     client_obj = DbTools.get_conn(db_config=online_config, database="hitech")
    #     cursor = client_obj.cursor(cursor=DbTools.dictCursor)
    #     record = None
    #     try:
    #         cursor.execute(sql)
    #         record = cursor.fetchone()
    #     except Exception as err:
    #         g.logger.error("select file path error error={err} sql={sql}".format(err=err, sql=sql))
    #     if not record:
    #         g.logger.error("未搜索到附件")
    #         return
    #     # record = "/sda/GR_2020/ctp/GR_65536/catalogue.pdf"
    #     path = materials_path + "\\{}_{}\\{}\\{}_{}".format(site_type, g.year, web_type, site_type, g.co_id)
    #
    #     if not os.path.exists(path):
    #         os.mkdir(path)
    #     db_path = record.get("file_path")
    #     remote_path = "/sda" + db_path
    #     local_path = path + "\\" + os.path.basename(db_path)
    #     try:
    #         ssh = SSH(ip="192.168.1.50", username="root", password="abc.123")
    #         ssh.connect()
    #         ssh._sftp_get(remotefile=remote_path.replace("\\", "/"), localfile=local_path)
    #     except SSHException as err:
    #         g.logger.error("连接 文件服务器错误， 应该与 192.168.1.50 机器在同一局域网下, err={err}".format(err=err))
    #     finally:
    #         ssh.close()
    #
    #     return local_path

    @staticmethod
    def get_year(tip_str):
        pattern = r'\d{4}'

        res = re.search(pattern, tip_str)
        if res:
            return int(res.group())
        else:
            return None

    # # # # # # # # # #  返回按钮点击
    @staticmethod
    def click_back_btn(btn_loc, driver=None):
        if not driver:
            raise NameError("driver is not defind. custom--")
        BM.click(driver=driver, ele_loc=btn_loc)

    @staticmethod
    def handle_ia_ids(id_str="", plus_str="", replace_zero=True):

        sp = id_str.replace(",", "")

        sp = [i for i in sp if i != "0"]
        a = []
        for i in sp:
            if i == "0" and replace_zero:
                a.append("其他")
            else:
                a.append(plus_str + i.zfill(2))
        return "\n".join(a)

    @staticmethod
    def join_and_replace(str_list):
        a = ""
        if isinstance(str_list, list):
            a = "".join(str_list)
        if isinstance(str_list, Iterable):
            a = "".join(str_list)
        else:
            a = str(str_list)
        a = a.strip()
        a.replace("\n", "").replace("\t", "").replace("\xa0", "")
        return a

    # @staticmethod
    # def get_first(str_list):
    #     if isinstance(str_list, list) and len(str_list) > 0:
    #         if len(str_list) > 0:
    #             return str_list[0]
    #         else:
    #             return "".join(str_list)
    #     return str_list

    @staticmethod
    def check_lenth(li):
        li_set = list(set(li))
        if len(li) == len(li_set):
            return True
        else:
            return False

    # def __init__(self, name):
    #     self.name = name

    # def __call__(self, *args, **kwargs):
    #     print(self.name)
    #     print(sys._getframe().f_code.co_name)


if __name__ == "__main__":
    # a = globals()["BM"](name="123test")
    # print(a.name)
    # a = BM.get_host()
    # print(a)
    # a()

    # g.co_id = 463636
    # g.year = 2020
    # status = {"stat_id": "GR2020463636"}
    # f = BM.get_file_operate(status, operate="split")
    # print(f)

    print(f"---{BM.get_first([])}----")

